#include "hits.h"
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "vector.h"
#include "stats.h"

int *hits_pm (Digraph H, double ksi, double epsilon, double* aut, double* hub, int result)
{
  Vertex v;
  int iter = 0;
  int t0, t1, i;
  int *rank;
  double residual_a, residual_h, time;
  double *old_aut, *old_hub, *ans1, *ans2;

  residual_a = residual_h = 1.0;
  old_aut = malloc(H->V * sizeof(double));
  old_hub = malloc(H->V * sizeof(double));
  ans1 = malloc(H->V * sizeof(double));
  ans2 = malloc(H->V * sizeof(double));
  for (i = 0; i < H->V; i++) aut[i] = hub[i] = 1 / H->V;

  t0 = clock();
  while (residual_a >= epsilon && residual_h >= epsilon) {
    //prevx = x;
    for (v = 0; v < H->V; v++) {
      old_aut[v] = aut[v];
      old_hub[v] = hub[v];
    }
    iter++;
    vector_matrix_product(aut, H, 1, ans1);
    vector_matrix_product(ans1, H, 0, aut);
    vector_matrix_product(hub, H, 0, ans2);
    vector_matrix_product(ans2, H, 1, hub);
    ksi_adjust(aut, ksi, old_aut, H->V);
    ksi_adjust(hub, ksi, old_hub, H->V);
    normalize(aut, H->V);
    normalize(hub, H->V);
    point_sub(aut, old_aut, old_aut, H->V);
    point_sub(hub, old_hub, old_hub, H->V);
    residual_a = norm1(old_aut, H->V);
    residual_h = norm1(old_hub, H->V);
  }
  t1 = clock();
  time = ((double)(t1 - t0)) / CLOCKS_PER_SEC;
  

  if (result == 0) rank = find_top_values(aut, H->V, H->V);
  else rank = find_top_values(hub, H->V, H->V);
  print_stats(H, iter, time, ksi, epsilon, "HITS", "ksi");
  
  // Free routines
  free(old_aut);
  free(old_hub);
  free(ans1);
  free(ans2);
  return rank;
}

void ksi_adjust (double *aut, double ksi, double *old_aut, int n)
{
  Vertex v;
  double value = (1.0 - ksi) / n;
  
  for (v = 0; v < n; v++) {
    aut[v] *= ksi;
    aut[v] += value;
  }
}

void print_hits(double *aut, double *hub, int V)
{
  Vertex v;

  for (v = 0; v < V; v++) {
    if (v % 10 == 0) printf("\n");
    printf("AUT[%d] = %.4f ", v, aut[v]);
  }
  printf("\n");
  for (v = 0; v < V; v++) {
    if (v % 10 == 0) printf("\n");
    printf("HUB[%d] = %.4f ", v, hub[v]);
  }
  printf("\n");
}

